from fastapi import FastAPI, Request
from fastapi.routing import APIRoute
from app.core.config import settings
from starlette.middleware.cors import CORSMiddleware
from app.api.main import api_router
from app.core.redis import init_redis, close_redis
from app.core.http_client import HttpClient
from app.middlewares.response_wrapper import response_wrapper
from app.middlewares.exception_handler import (
    validation_exception_handler, 
    global_exception_handler, 
    http_exception_handler,
)
from fastapi.exceptions import RequestValidationError, HTTPException
from app.core.logger import init_logger, attach_sql_logger
from app.core.session import async_engine

# 初始化日志记录器(默认api模式)
logger = init_logger("api")

def custom_generate_unique_id(route: APIRoute) -> str:
    return f"{route.tags[0]}-{route.name}"

# 定义lifespan事件处理器
async def lifespan(app: FastAPI):
    logger.info("Application startup")
    if not async_engine.sync_engine:
        logger.error("Async engine not initialized")
        raise RuntimeError("Async engine not initialized")
    attach_sql_logger(async_engine.sync_engine, "api")
    # 应用启动时初始化Redis
    await init_redis()
    HttpClient.get_client()

    yield # 应用运行中

    # 应用关闭时关闭Redis连接
    logger.info("Application shutdown")
    await close_redis()
    await HttpClient.close()

app = FastAPI(title=settings.PROJECT_NAME,
    openapi_url=f"{settings.API_V1_STR}/openapi.json",
    generate_unique_id_function=custom_generate_unique_id,
    lifespan=lifespan,
)

# Set all CORS enabled origins
if settings.all_cors_origins:
    app.add_middleware(
        CORSMiddleware,
        # allow_origins=settings.all_cors_origins,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

# 注册响应包装中间件
app.middleware("http")(response_wrapper)

# 注册异常处理中间件
app.add_exception_handler(RequestValidationError, validation_exception_handler)
app.add_exception_handler(HTTPException, http_exception_handler)
app.add_exception_handler(Exception, global_exception_handler)

app.include_router(api_router, prefix=settings.API_V1_STR)